﻿using System;
using System.Xml;

namespace Graphe.Collations
{
    public class Variant : ICollationElement, IComparable<Variant>
    {
        #region Constructor

        public Variant()
        {
            BaseWitnesses = new ManuscriptCollection();
            Readings = new ReadingCollection();
        }

        #endregion
        #region Public Properties

        /// <summary>
        /// The base text of the section collated.
        /// </summary>
        public string BaseText { get; set; }

        /// <summary>
        /// Correction witnesses supporting the base text.
        /// </summary>
        public ManuscriptCollection BaseWitnesses { get; set; }

        /// <summary>
        /// The readings against the base text.
        /// </summary>
        public ReadingCollection Readings { get; set; }

        /// <summary>
        /// If the variant refers to a numbered word or words in the base text, that is
        /// specified here.
        /// </summary>
        public string Number { get; set; }

        #endregion
        #region ICollationElement Members

        public void Parse(XmlReader reader, CollationDebugMessages debugMessages)
        {
            if (reader.Name != "Variant")
            {
                debugMessages.Add(String.Format("Unknown xml trying to parse variant: {0}.", reader.ReadOuterXml()));
            }
            else
            {
                reader.ReadToFollowing("Base");
                reader.ReadToDescendant("Text");

                if (reader.AttributeCount > 0)
                {
                    reader.MoveToFirstAttribute();

                    do
                    {
                        if (reader.Name == "Number")
                        {
                            Number = reader.ReadContentAsString();
                        }
                        else
                        {
                            debugMessages.Add(String.Format("Attribute '{0}' with value '{1}' for variant is unknown and will not be persisted in the in-memory model. This also means it won't be saved after you change the collation.", reader.Name, reader.ReadContentAsString()));
                        }
                    } while (reader.MoveToNextAttribute());
                }

                reader.Read();
                this.BaseText = reader.ReadContentAsString().Trim();

                do
                {
                    reader.Read();
                } while (reader.Name != "Manuscripts" && reader.Name != "Readings");

                if (reader.Name == "Manuscripts")
                {
                    BaseWitnesses = new ManuscriptCollection();
                    BaseWitnesses.Parse(reader, debugMessages);
                    reader.ReadToFollowing("Readings");
                }

                Readings = new ReadingCollection();
                Readings.Parse(reader, debugMessages);
            }
        }

        public void Render(XmlTextWriter writer)
        {
            writer.WriteStartElement("Variant");
            {
                writer.WriteStartElement("Base");
                {
                    writer.WriteStartElement("Text");

                    if (!String.IsNullOrEmpty(Number))
                    {
                        writer.WriteAttributeString("Number", Number);
                    }

                    writer.WriteString(BaseText);
                    writer.WriteEndElement();

                    if (BaseWitnesses.Count > 0)
                    {
                        writer.WriteStartElement("Manuscripts");

                        foreach (Manuscript manuscript in BaseWitnesses)
                        {
                            manuscript.Render(writer);
                        }

                        writer.WriteEndElement();
                    }

                }
                writer.WriteEndElement();




                writer.WriteStartElement("Readings");

                foreach (Reading reading in Readings)
                {
                    reading.Render(writer);
                }

                writer.WriteEndElement();
            }
            writer.WriteEndElement();
        }

        #endregion

        #region IComparable<Variant> Members

        public int CompareTo(Variant other)
        {
            if (this.BaseText != other.BaseText || this.Number != other.Number)
                return -1;

            if (this.BaseWitnesses.CompareTo(other.BaseWitnesses) == -1)
                return -1;

            if (this.Readings.CompareTo(other.Readings) == -1)
                return -1;

            return 0;
        }

        #endregion
    }
}
